package com.DB;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;

import Variabilize.Chemin;

import com.*;
import com.Comparaisons.ArbreComparaisons;
import com.Comparaisons.Comparaison;

/**
 * DBCounter permet de compter le nombre d'occurences de relations entre différents atomes
 *  dans une même base de données
 * @author florent
 */
public class DBCounter {

	private DBConnector db = null; //connecteur à la base de données

	/**
	 * Construit un DBCounter
	 * @param db connecteur à la base de données
	 */
	public DBCounter(DBConnector db){
		this.db  = db;
	}


	/**
	 * Execute la requete de comptage "query" et compte le nombre de lignes obtenu en sortie
	 * @param query requete en mode Texte
	 * @return nombre de ligne engendrés par la requete
	 */
	public int compter(String query){

		Connection c = db.newConnection();

		ResultSet rs = db.executeQuery(query,c); 							//execute la requete 'query'
		ResultSet rs1 = db.executeQuery("SELECT FOUND_ROWS() as nb1",c);  //recupere le nombre de ligne obtenus

		int nb=0; //nombre de lignes

		try {
			//rs.next();   //charge rs   : les resultats de query
			rs1.next();  //charge rs1  : le nombre de lignes de rs

			nb=rs1.getInt("nb1");  // recupere le nombre de lignes de rs1

			rs1.close();  //ferme rs1
			rs.close();   //ferme rs

		} catch (SQLException e) {
			e.printStackTrace();
		}

		db.close(c);

		return nb;
	}

	/**
	 * Compte le nombre de liens entre deux modèles
	 * 
	 *
	 * (
	 * 		Requete a construire : (les <i> seront remplacés
	 * 
	 * 		SELECT m1.id,m2.id as nb 
	 * 		FROM modele_<nom> m1, modele_<nom> m2
	 * 		WHERE m1.arg<N0> <> m2.arg<N1>
	 * 		<AND m1.id <> m2.id>
	 * 		AND m1.truth=<!m1.isnegative> AND m2.truth=<!m2.isnegative>
	 * 			<	Rajoute l'extension 
	 * 					AND m1.arg<N0> = m2.arg<N1>
	 * 				pour chaque comparaison à deux arguments
	 * 			>
	 * )
	 * 
	 * puis compte le nombre de lignes
	 * 
	 * @param m1 modèle source
	 * @param m2 modèle à comparer
	 * @param Arbre des comparaisons d'arguments à effectuer
	 */
	public void count(Modele m1, Modele m2, LinkedList<ArbreComparaisons> comparaisons){

		for(ArbreComparaisons x : comparaisons){  //pour chaque comparaisons à éxécuter

			StringBuffer sb_count_x = new StringBuffer(); //Construit un string qui va contenir la requete

			sb_count_x.append("SELECT m1.id, m2.id ")
			.append("FROM modele_").append(m1.getPredicat()).append(" m1,")
			.append("modele_").append(m2.getPredicat()).append(" m2")
			.append(" WHERE m1.arg").append(x.getNoeud().getN0())
			.append(" = ").append("m2.arg").append(x.getNoeud().getN1());

			if(m1.equals(m2)) 
				sb_count_x.append(" AND m1.id <> m2.id ");

			if(m1.isNegative())
				sb_count_x.append(" AND m1.truth='0' ");
			else
				sb_count_x.append(" AND m1.truth='1' ");

			if(m2.isNegative())
				sb_count_x.append(" AND m2.truth='0' ");
			else
				sb_count_x.append(" AND m2.truth='1' ");

			x.getNoeud().setNb(compter(sb_count_x.toString()));


			/**
			 * Rajoute l'extension 
			 *      AND m1.arg<N0> = m2.arg<N1>
			 * pour chaque comparaison à deux arguments
			 */
			for(ArbreComparaisons y : x.getBranches()){

				StringBuffer sb_count_y = new StringBuffer();
				sb_count_y.append(sb_count_x.toString());

				sb_count_y.append(" AND m1.arg").append(y.getNoeud().getN0())
				.append(" = m2.arg").append(y.getNoeud().getN1());

				y.getNoeud().setNb(compter(sb_count_y.toString()));

			}
		}

	}

	public int count(Modele m1, Modele m2, Comparaison comparaison){

		StringBuffer sb_count_x = new StringBuffer(); //Construit un string qui va contenir la requete

		sb_count_x.append("SELECT m1.id, m2.id ")
		.append("FROM modele_").append(m1.getPredicat()).append(" m1,")
		.append("modele_").append(m2.getPredicat()).append(" m2")
		.append(" WHERE m1.arg").append(comparaison.getN0())
		.append(" = ").append("m2.arg").append(comparaison.getN1());

		if(m1.equals(m2)) 
			sb_count_x.append(" AND m1.id <> m2.id ");

		if(m1.isNegative())
			sb_count_x.append(" AND m1.truth='0' ");
		else
			sb_count_x.append(" AND m1.truth='1' ");

		if(m2.isNegative())
			sb_count_x.append(" AND m2.truth='0' ");
		else
			sb_count_x.append(" AND m2.truth='1' ");


		int nb= compter(sb_count_x.toString());
		comparaison.setNb(nb);

		return nb;
	}

	public int count(Modele m1, Modele m2, Comparaison comparaison, Comparaison comparaison2){

		StringBuffer sb_count_x = new StringBuffer(); //Construit un string qui va contenir la requete

		sb_count_x.append("SELECT m1.id, m2.id ")
		.append("FROM modele_").append(m1.getPredicat()).append(" m1,")
		.append("modele_").append(m2.getPredicat()).append(" m2")
		.append(" WHERE m1.arg").append(comparaison.getN0())
		.append(" = ").append("m2.arg").append(comparaison.getN1());

		if(m1.equals(m2)) 
			sb_count_x.append(" AND m1.id <> m2.id ");

		if(m1.isNegative())
			sb_count_x.append(" AND m1.truth='0' ");
		else
			sb_count_x.append(" AND m1.truth='1' ");

		if(m2.isNegative())
			sb_count_x.append(" AND m2.truth='0' ");
		else
			sb_count_x.append(" AND m2.truth='1' ");


		StringBuffer sb_count_y = new StringBuffer();
		sb_count_y.append(sb_count_x.toString());

		sb_count_y.append(" AND m1.arg").append(comparaison2.getN0())
		.append(" = m2.arg").append(comparaison2.getN1());

		int nb= compter(sb_count_y.toString());
		comparaison2.setNb(nb);

		return nb;
	}

	public int count(LinkedList<Chemin> chemin){

		StringBuffer sb_count_x = new StringBuffer(); //Construit un string qui va contenir la requete

		sb_count_x.append("SELECT m1.id FROM ");

		sb_count_x.append(" modele_").append(chemin.get(0).getModele().getPredicat()).append(" m0");
		sb_count_x.append(" , modele_").append(chemin.get(0).getModele2().getPredicat()).append(" m1");

		for(int i=1;i<chemin.size();++i){
			sb_count_x.append(" , modele_").append(chemin.get(i).getModele2().getPredicat()).append(" m").append(i+1);
		}

		sb_count_x.append(" WHERE m0.arg").append(chemin.get(0).getComparaison().getN0()).append("=")
		.append("m1.arg").append(chemin.get(0).getComparaison().getN1());
		
		if(chemin.get(0).getModele().isNegative())
			sb_count_x.append(" AND m").append(0).append(".truth='0' ");
		else
			sb_count_x.append(" AND m").append(0).append(".truth='1' ");
		
		if(chemin.get(0).getModele2().isNegative())
			sb_count_x.append(" AND m").append(1).append(".truth='0' ");
		else
			sb_count_x.append(" AND m").append(1).append(".truth='1' ");

		for(int i=1;i<chemin.size();++i){

			sb_count_x.append(" AND ");
			sb_count_x.append("m").append(i)
			.append(".arg").append(chemin.get(i).getComparaison().getN0()).append("=");
			
			sb_count_x.append("m").append(i+1)
			.append(".arg").append(chemin.get(i).getComparaison().getN1());
			
			if(chemin.get(i).getModele2().isNegative())
				sb_count_x.append(" AND m").append(i+1).append(".truth='0' ");
			else
				sb_count_x.append(" AND m").append(i+1).append(".truth='1' ");
			
		}
		
		int nb = compter(sb_count_x.toString());

		
		return nb;
	}

}
